package net.saralab;

import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.event.FMLServerStartingEvent;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent;
import cpw.mods.fml.common.network.FMLEventChannel;
import cpw.mods.fml.common.network.FMLNetworkEvent.ClientCustomPacketEvent;
import cpw.mods.fml.common.network.FMLNetworkEvent.ServerCustomPacketEvent;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
import cpw.mods.fml.relauncher.FMLInjectionData;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.URLDecoder;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import javax.imageio.ImageIO;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.IResource;
import net.minecraft.command.ICommand;
import net.minecraft.command.ICommandSender;
import net.minecraft.crash.CrashReport;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StringUtils;
import net.minecraft.world.WorldServer;
import net.minecraftforge.client.event.TextureStitchEvent.Post;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import org.apache.logging.log4j.Level;

@Mod(modid = "AntiCheat3", name = "AntiCheat3", version = "AntiCheat3")
public class AssWeCan {
	public static final String MODID = "AntiCheat3";
	public static final String NAME = "AntiCheat3";
	public static final String VERSION = "3.3.1";
	private static LinkedHashMap<String, String> D = new LinkedHashMap();
	private static LinkedHashMap<String, link> Boy = new LinkedHashMap();
	private static Map<EntityPlayerMP, n> nex = Collections.synchronizedMap(new HashMap());
	private static List<String> T = new ArrayList();
	private static Configuration E;
	private static ChatComponentText Door = new ChatComponentText("Invalid client data");
	private static int My;
	private static FMLEventChannel shoulder;

	@Mod.EventHandler
	public void preInit(FMLPreInitializationEvent event) {
		MinecraftForge.EVENT_BUS.register(new yi());
		FMLCommonHandler.instance().bus().register(new yi());
		shoulder = NetworkRegistry.INSTANCE.newEventDrivenChannel("AntiCheat3");
		shoulder.register(this);
		E = new Configuration(new File(
				String.format("%s/%s.cfg", new Object[] { event.getModConfigurationDirectory(), "AntiCheat" })));
		new Timer().schedule(new Go(), 0L, 3000L);
	}

	@Mod.EventHandler
	public void Init(FMLInitializationEvent event) {
	}

	@Mod.EventHandler
	@SideOnly(Side.CLIENT)
	public void clientPostInit(FMLPostInitializationEvent event) {
		FA();
		Q();
	}

	@Mod.EventHandler
	@SideOnly(Side.SERVER)
	public void serverPostInit(FMLPostInitializationEvent event) {
		o();
	}

	@Mod.EventHandler
	@SideOnly(Side.SERVER)
	public void serverLoad(FMLServerStartingEvent p) {
		p.registerServerCommand(new RBQ());
	}

	private String mi(File l) throws IOException, NoSuchAlgorithmException {
		FileInputStream S = new FileInputStream(l.getAbsoluteFile());
		MappedByteBuffer t = S.getChannel().map(FileChannel.MapMode.READ_ONLY, 0L, l.length());
		MessageDigest d = MessageDigest.getInstance("MD5");
		d.update(t);
		BigInteger i = new BigInteger(1, d.digest());
		String v = i.toString(16);
		S.close();
		return v;
	}

	private void Q() {
		E.load();
		Property p = E.get("general", "MaxWaitTime", 5000);
		p.comment = "Time wait for client reply at most (ms)";
		HashSet sh = new HashSet(D.values());
		E.get("MD5List", "ServerConfig", (String[]) sh.toArray(new String[sh.size()]));
		E.save();
	}

	private void o() {
		E.load();
		Property p = E.get("general", "MaxWaitTime", 5000);
		p.comment = "Time wait for client reply at most (ms)";
		My = p.getInt();
		if (My < 0) {
			My = 0;
		}
		List<ModContainer> a = Loader.instance().getModList();
		for (ModContainer b : a) {
			try {
				if (b.getModId().equalsIgnoreCase("AntiCheat3")) {
					File A = b.getSource();
					String c = mi(A);
					FMLLog.log(Level.INFO, "%s modMd5:%s", new Object[] { b.getName(), c });
					T.add(c);
					break;
				}
			} catch (NoSuchAlgorithmException e) {
				FMLLog.log(Level.ERROR, "%s:%s", new Object[] { b.getName(), e });
			} catch (IOException e) {
				T.add(b.getName());
			}
		}
		String[] m = E.get("MD5List", "ServerConfig", T.toArray(new String[T.size()])).getStringList();
		E.save();
		T.clear();
		for (int i = 0; i < m.length; i++) {
			T.add(m[i]);
		}
		FMLLog.info("Server MD5List:", new Object[0]);
		for (String g : T) {
			FMLLog.info("%s", new Object[] { g });
		}
	}

	@SubscribeEvent
	@SideOnly(Side.CLIENT)
	public void ahego(ClientCustomPacketEvent t) throws UnsupportedEncodingException {
		String c = new String(t.packet.payload().array()).replace(" ", "").trim();
		Collection<String> d = new HashSet(D.values());
		String n = "";
		for (String r : d) {
			n = n + r + ",";
		}
		if (!StringUtils.isNullOrEmpty(n)) {
			n = n.substring(0, n.length() - 1);
		}
		n = n + c;
		try {
			byte[] m = n.getBytes("UTF-8");
			ByteBuf a = Unpooled.wrappedBuffer(m);
			FMLProxyPacket k = new FMLProxyPacket(a, "AntiCheat3");
			shoulder.sendToServer(k);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	@SubscribeEvent
	@SideOnly(Side.SERVER)
	public void nano(ServerCustomPacketEvent n) throws UnsupportedEncodingException {
		String e = new String(n.packet.payload().array()).replace(" ", "").trim();
		String[] y = e.split(",");
		e = "";
		for (int i = 0; i < y.length - 2; i++) {
			e = e + y[i] + ",";
		}
		if (!StringUtils.isNullOrEmpty(e)) {
			e = e.substring(0, e.length() - 1).replace(" ", "").trim();
		}
		FMLLog.info("Client MD5:---%s", new Object[] { e });
		boolean d = false;
		if (!Boy.get(y[(y.length - 1)]).s.equals(y[(y.length - 2)])) {
			n.manager.closeChannel(Door);
			return;
		}
		for (int i = 0; i < y.length - 2; i++) {
			for (int j = 0; j < T.size(); j++) {
				if (T.get(j).equalsIgnoreCase(y[i])) {
					d = true;
					break;
				}
				d = false;
			}
			if (!d) {
				n.manager.closeChannel(Door);
				return;
			}
		}
		Boy.get(y[(y.length - 1)]).r = true;
	}

	private static String S(String o) {
		String r = "";
		try {
			MessageDigest d = MessageDigest.getInstance("MD5");
			d.update(o.getBytes());
			byte[] b = d.digest();

			StringBuffer u = new StringBuffer("");
			for (int t = 0; t < b.length; t++) {
				int i = b[t];
				if (i < 0) {
					i += 256;
				}
				if (i < 16) {
					u.append("0");
				}
				u.append(Integer.toHexString(i));
			}
			r = u.toString();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return r;
	}

	private void s(File l) {
		Object[] o = FMLInjectionData.data();
		String i = (String) o[4];
		if (l.isDirectory()) {
			File[] s = l.listFiles();
			for (File a : s) {
				if ((!a.isDirectory()) || (a.getName() == i)) {
					if ((a.getName().endsWith(".jar")) || (a.getName().endsWith(".zip"))
							|| (a.getName().endsWith(".litemod"))) {
						try {
							String M = mi(a);
							if (!D.containsValue(M)) {
								FMLLog.info("modjar----%s:%s", new Object[] { a.getName(), M });
								D.put(a.getName(), M);
							}
						} catch (NoSuchAlgorithmException e) {
							e.printStackTrace();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
					s(a);
				}
			}
		}
	}

	private void FA() {
		try {
			Class L = Class.forName("net.minecraft.client.main.Main");
			String p = L.getProtectionDomain().getCodeSource().getLocation().getPath().split("!")[0];
			p = URLDecoder.decode(p, "UTF-8").substring(6);
			File j = new File(p);
			String m = mi(j);
			FMLLog.info("jar---%s:%s", new Object[] { j.getName(), m });
			D.put(j.getName(), m);
		} catch (ClassNotFoundException e) {
			FMLLog.log(Level.ERROR, "%s:%s", new Object[] { "GameJarERROR", e });
		} catch (NoSuchAlgorithmException e) {
			FMLLog.log(Level.ERROR, "%s:%s", new Object[] { "GameJarERROR", e });
		} catch (IOException e) {
			FMLLog.log(Level.ERROR, "%s:%s", new Object[] { "GameJarERROR", e });
		}
		List<ModContainer> s = Loader.instance().getModList();
		for (ModContainer d : s) {
			File i = d.getSource();
			try {
				if ((d.getName().equals("Forge Mod Loader")) || (d.getName().equals("Minecraft Forge"))
						|| (!d.getName().equals("Minecraft Coder Pack"))) {
					String r = mi(i);
					FMLLog.info("modjar----%s:%s", new Object[] { d.getName(), r });
					D.put(d.getName(), r);
					Object[] o = FMLInjectionData.data();
					File c = (File) o[6];
					File b = new File(c, "mods");
					s(b);
				}
			} catch (NoSuchAlgorithmException e) {
				FMLLog.log(Level.ERROR, "%s:%s", new Object[] { d.getName(), e });
			} catch (IOException e) {
				FMLLog.log(Level.ERROR, "%s:%s", new Object[] { d.getName(), e });
				if (e(i)) {
					Minecraft.getMinecraft().crashed(new CrashReport("error", new Throwable("Not allow unpacked mod")));
				}
			}
		}
	}

	private boolean e(File e) {
		if (e.isDirectory()) {
			File[] l = e.listFiles();
			for (File f : l) {
				if (f.getName().endsWith(".class")) {
					FMLLog.log(Level.ERROR, "[%s] ,Not allow unpacked mod", new Object[] { f.getName() });
					return true;
				}
				if (e(f)) {
					return true;
				}
			}
		}
		return false;
	}

	private static String g(int g) {
		String b = "abcdef0123456789";
		Random o = new Random();
		StringBuffer e = new StringBuffer();
		for (int i = 0; i < g; i++) {
			int n = o.nextInt(b.length());
			e.append(b.charAt(n));
		}
		return e.toString();
	}

	private void h(EntityPlayerMP h) {
		n o = nex.get(h);
		if ((Boy.get(S(h.getDisplayName())) != null) && (!o.d) && (o.e + My < System.currentTimeMillis())) {
			if (!Boy.get(S(h.getDisplayName())).r) {
				h.playerNetServerHandler.kickPlayerFromServer("Timed out");
			}
			o.d = true;
			Boy.remove(S(h.getDisplayName()));
		}
	}

	public class U extends TimerTask {
		private EntityPlayerMP u;

		U(EntityPlayerMP u) {
			this.u = u;
		}

		@Override
		public void run() {
			if (g(this.u.getDisplayName()) != null) {
				AssWeCan.this.h(this.u);
			}
		}

		private EntityPlayer g(String e) {
			for (WorldServer s : MinecraftServer.getServer().worldServers) {
				EntityPlayer p = s.getPlayerEntityByName(e);
				if (p != null) {
					return p;
				}
			}
			return null;
		}
	}

	public class Go extends TimerTask {
		public Go() {
		}

		@Override
		public void run() {
			if (!AssWeCan.nex.isEmpty()) {
				Iterator<Map.Entry<EntityPlayerMP, AssWeCan.n>> it = AssWeCan.nex.entrySet().iterator();
				while (it.hasNext()) {
					Map.Entry<EntityPlayerMP, AssWeCan.n> y = it.next();
					EntityPlayerMP r = y.getKey();
					AssWeCan.n info = y.getValue();
					if (info.d) {
						it.remove();
					} else {
						AssWeCan.this.h(r);
					}
				}
			}
			if (!AssWeCan.Boy.isEmpty()) {
				Iterator<Map.Entry<String, AssWeCan.link>> it = AssWeCan.Boy.entrySet().iterator();
				while (it.hasNext()) {
					Map.Entry<String, AssWeCan.link> r = it.next();
					AssWeCan.link s = r.getValue();
					if (System.currentTimeMillis() - s.t > 30000L) {
						it.remove();
					}
				}
			}
		}
	}

	private class n {
		long e;
		boolean d;

		n(long d) {
			this.e = d;
			this.d = false;
		}
	}

	private class link {
		long t;
		String s;
		boolean r;

		link(String s, long t) {
			this.t = t;
			this.s = s;
			this.r = false;
		}
	}

	public class yi {
		public yi() {
		}

		@SubscribeEvent
		@SideOnly(Side.CLIENT)
		public void ts(Post r) {
			ResourceLocation s = new ResourceLocation("textures/blocks/stone.png");
			try {
				IResource ib = Minecraft.getMinecraft().getResourceManager().getResource(s);
				BufferedImage b = ImageIO.read(ib.getInputStream());
				for (int i = 0; i < b.getWidth(); i++) {
					for (int j = 0; j < b.getHeight(); j++) {
						if (b.getRGB(i, j) >> 24 == 0) {
							Minecraft.getMinecraft()
									.crashed(new CrashReport("error", new Throwable("Not allow transparent texture")));
							return;
						}
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		@SubscribeEvent
		@SideOnly(Side.SERVER)
		public void Gay(PlayerLoggedInEvent error) throws UnsupportedEncodingException {
			if ((error.player instanceof EntityPlayerMP)) {
				EntityPlayerMP r = (EntityPlayerMP) error.player;
				AssWeCan.nex.put(r, new AssWeCan.n(System.currentTimeMillis()));
				String M = AssWeCan.g(32);
				byte[] me = new String("," + M + "," + AssWeCan.S(r.getDisplayName())).getBytes("UTF-8");
				AssWeCan.Boy.put(AssWeCan.S(r.getDisplayName()), new AssWeCan.link(M, System.currentTimeMillis()));
				ByteBuf d = Unpooled.wrappedBuffer(me);
				FMLProxyPacket k = new FMLProxyPacket(d, "AntiCheat3");
				AssWeCan.shoulder.sendTo(k, r);
				new Timer().schedule(new AssWeCan.U(r), AssWeCan.My + 50);
			}
		}
	}

	public class RBQ implements ICommand {
		private static final String help = "Type \"/ac3 help\" for more infomation";

		public RBQ() {
		}

		@Override
		public int compareTo(Object arg0) {
			return 0;
		}

		@Override
		public String getCommandName() {
			return "ac3";
		}

		@Override
		public String getCommandUsage(ICommandSender p_71518_1_) {
			return null;
		}

		@Override
		public List getCommandAliases() {
			return null;
		}

		@Override
		public void processCommand(ICommandSender cs, String[] args) {
			if (args.length == 1) {
				if ("reload".equalsIgnoreCase(args[0])) {
					AssWeCan.this.o();
					cs.addChatMessage(new ChatComponentText("Configuration reloaded"));
					return;
				}
				if ("help".equalsIgnoreCase(args[0])) {
					cs.addChatMessage(new ChatComponentText("/ac3 reload - Reload configuration"));
					return;
				}
			}
			cs.addChatMessage(new ChatComponentText("Type \"/ac3 help\" for more infomation"));
		}

		@Override
		public boolean canCommandSenderUseCommand(ICommandSender cs) {
			boolean hasPermission = false;
			if ((cs instanceof EntityPlayer)) {
				EntityPlayer player = (EntityPlayer) cs;
				hasPermission = MinecraftServer.getServer().getConfigurationManager()
						.func_152596_g(player.getGameProfile());
			} else if ((cs instanceof DedicatedServer)) {
				hasPermission = true;
			}
			return hasPermission;
		}

		@Override
		public List addTabCompletionOptions(ICommandSender p_71516_1_, String[] p_71516_2_) {
			return null;
		}

		@Override
		public boolean isUsernameIndex(String[] p_82358_1_, int p_82358_2_) {
			return false;
		}
	}
}
